﻿using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace LaunchPad.Core
{
    public sealed class ProductFactory : INotifyPropertyChanged
    {
        private ProductCollection _products = new ProductCollection();

        private ProductFactory()
        {
        }

        public static ProductFactory Instance
        {
            get { return Nested.instance; }
        }

        public static ProductCollection Products
        {
            get { return Instance._products; }
            set
            {
                if (Instance._products != value)
                {
                    Instance._products = value;
                    Instance.OnPropertyChanged("Products");
                }
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public bool TryGetProduct(IdRef<Product> productReference, out Product product)
        {
            try
            {
                product = Products.First(p => p.Id == productReference.Id);
                return true;
            }
            catch (InvalidOperationException)
            {
                product = null;
                return false;
            }
        }

        public Product GetProduct(string name)
        {
            return Products.First(ec => ec.Name == name);
        }

        public void AddProduct(Product product)
        {
            if (product.Id == Guid.Empty)
                throw new ArgumentException("Effect class must have a non-empty id value");

            if (Products.Any(ec => ec.Id == product.Id))
                throw new ArgumentException("Effect class with this id already exists");

            Products.Add(product);
        }

        public void RemoveProduct(Guid id)
        {
            var toRemove = Products.Where(p => p.Id == id).ToList();
            foreach (var product in toRemove)
                Products.Remove(product);
        }

        //public void Save(string file)
        //{
        //    Type[] otherTypes = {typeof (DefaultProduct)};
        //    var serializer = new XmlSerializer(typeof (ProductCollection), otherTypes);
        //    using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write))
        //    {
        //        serializer.Serialize(stream, Products);
        //    }
        //}

        //public void Load(string file)
        //{
        //    try
        //    {
        //        Type[] otherTypes = {typeof (DefaultProduct)};
        //        var serializer = new XmlSerializer(typeof (ProductCollection), otherTypes);
        //        using (var stream = new FileStream(file, FileMode.Open))
        //        {
        //            if (stream.Length > 0)
        //                Products = (ProductCollection) serializer.Deserialize(stream);
        //        }
        //    }
        //    catch (FileNotFoundException)
        //    {
        //    }
        //}

        private void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }

        #region Nested type: Nested

        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit

            internal static readonly ProductFactory instance = new ProductFactory();

            static Nested()
            {
                Instance.AddProduct(new DefaultProduct());
            }
        }

        #endregion
    }

    public class DefaultProduct : Product
    {
        public DefaultProduct()
            : base("Default")
        {
            LeadIn = TimeSpan.Zero;
            LeadOut = TimeSpan.FromMilliseconds(500);
            Id = new Guid("6E9CD5C2-F139-11DF-A44F-ECD4DFD72085");
        }
    }
}